home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / imlib / port / sgi / gen_drv.c next >
C/C++ Source or Header  |  1995-09-06  |  8KB  |  337 lines

  1.  
  2. #define NUM_CHANNELS 8
  3. #define STDOUT_FD driver_out_fd
  4. #define STDIN_FD  driver_in_fd
  5.  
  6.  
  7.  
  8. #define DOUT_NAME  "/tmp/sfxdrv.signal"
  9. #define DIN_NAME "/tmp/sfxdrv.command"
  10.  
  11.  
  12. enum { SFXCMD_QUIT,
  13.        SFXCMD_REGISTER,
  14.        SFXCMD_UNREGISTER,
  15.        SFXCMD_PLAY
  16.      };
  17.  
  18.  
  19. class sfx_handle
  20. {
  21.   public :
  22.   int          shm_id; 
  23.   void         *shm_data_pointer;
  24.   sfx_handle   *next;  
  25.   long         size;
  26.   int          use_count;
  27. } ;
  28.  
  29.  
  30.  
  31. int driver_out_fd,driver_in_fd;
  32. sfx_handle *sfx_list=NULL;
  33.  
  34.  
  35.  
  36. #define TOTAL_SIGS 29
  37.  
  38. int sigs[TOTAL_SIGS]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,
  39.               SIGABRT,SIGIOT,SIGBUS,SIGFPE,SIGKILL,
  40.               SIGUSR1,SIGSEGV,SIGUSR2,SIGPIPE,SIGALRM,
  41.               SIGTERM,SIGCHLD,SIGCONT,SIGSTOP,
  42.               SIGTSTP,SIGTTIN,SIGTTOU,SIGIO,
  43.               SIGURG,SIGXCPU,SIGXFSZ,SIGVTALRM,SIGPROF,
  44.               SIGWINCH};
  45.  
  46. struct channel
  47. {
  48.   unsigned char *data;         // next data to be qued
  49.   long left;                   // how much is left to play?  
  50.   unsigned char volume;        // indexed into volume table
  51.   unsigned long add_time;      // time at which the channel started playing
  52.   sfx_handle *snd;             // pointer to actual sound, so delete can stop us if need be
  53. } channels[NUM_CHANNELS];
  54.  
  55. #define uchar unsigned char
  56. unsigned char buf[BUF_SIZE];   // mixing buffer
  57.  
  58. uchar volume_table[256*32];    // 32 volume settings
  59.  
  60. // add a new sound effect into the channel list, if no free channel
  61. // oldest gets replaced with new sound
  62. void play(sfx_handle *snd, unsigned char volume)
  63. {
  64.   int i,free_channel=-1;
  65.   unsigned long oldest_channel=0,
  66.                 oldest_channel_time=10000,
  67.                 newest_channel_time=0;
  68.  
  69.   for (i=0;i<NUM_CHANNELS;i++)
  70.   {
  71.     if (channels[i].data)
  72.     { 
  73.       int my_time=channels[i].add_time;
  74.       if (my_time<oldest_channel_time)
  75.       {
  76.     oldest_channel=i;
  77.     oldest_channel_time=my_time;
  78.       }
  79.       if (my_time>newest_channel_time)
  80.     newest_channel_time=my_time;
  81.     } else free_channel=i;
  82.   }
  83.   
  84.   if (free_channel==-1)
  85.     free_channel=oldest_channel;
  86.  
  87.   channels[free_channel].snd=snd;
  88.   channels[free_channel].add_time=newest_channel_time+1;
  89.   channels[free_channel].data=(uchar *)snd->shm_data_pointer;
  90.   channels[free_channel].left=snd->size;
  91.   channels[free_channel].volume=volume*32/128;
  92. }
  93.  
  94.  
  95. int output_sounds()  // return 0 if no sounds to ouput
  96. {
  97.   unsigned char *s;
  98.   int i,j,bytes=0;  
  99.   
  100.   signed short sums[BUF_SIZE],run_size,*sp;
  101.   memset(sums,0,BUF_SIZE*sizeof(short));
  102.   for (j=0;j<NUM_CHANNELS;j++)
  103.   {
  104.     if (channels[j].data)
  105.     {
  106.       if (channels[j].left<BUF_SIZE)    // hom many bytes will this channel run for?
  107.         run_size=channels[j].left;
  108.       else run_size=BUF_SIZE;
  109.  
  110.       if (run_size>bytes)          // how many bytes to output?
  111.         bytes=run_size;
  112.       
  113.       // add the chanels together into a short
  114.       for (i=0,sp=sums;i<run_size;i++,sp++)
  115.       {
  116.     uchar cur_data=*(channels[j].data++);
  117.     short vol_data=volume_table[cur_data+channels[j].volume*256];
  118.         *sp+=vol_data-128;
  119.       }
  120.  
  121.       if (channels[j].left<=BUF_SIZE)
  122.         channels[j].data=NULL;
  123.       else channels[j].left-=BUF_SIZE;      
  124.     }
  125.   }
  126.     
  127.   for (i=0,sp=sums,s=buf;i<BUF_SIZE;i++,s++,sp++)
  128.   {
  129. #ifdef __linux__
  130.     if (*sp<-128) *s=0;
  131.     else if (*sp>127) *s=255;
  132.     else *s=(unsigned char)(*sp+128);
  133. #else
  134.     if (*sp<-128) *s=((unsigned char)((signed char)-128));
  135.     else if (*sp>127) *s=((unsigned char)((signed char)127));
  136.     else *s=((unsigned char)((signed char)*sp));
  137. #endif
  138.  
  139.   }
  140.  
  141.  
  142.   output_samples(buf,BUF_SIZE);
  143.  
  144.  
  145.   return 1;    // always say we have something, we will do blanks if nothing else
  146.   
  147. }
  148.  
  149.  
  150.  
  151. #ifdef __sgi
  152. void clean_up(...)
  153. #else
  154. void clean_up(int why)      // on exit unattach all shared memory links
  155. #endif
  156. {  
  157.   while (sfx_list)
  158.   {
  159.     shmdt((char *)sfx_list->shm_data_pointer);
  160.     if (shmctl(sfx_list->shm_id,IPC_RMID,NULL)!=0)
  161.       printf("shmctl failed, why?\n");
  162.     sfx_handle *last=sfx_list;
  163.     sfx_list=sfx_list->next;
  164.     free(last);
  165.   }
  166.   sound_uninit();
  167.   unlink(DIN_NAME);
  168.   unlink(DOUT_NAME);
  169. }
  170.  
  171. void die()
  172. { clean_up(0);
  173.   exit(0);
  174. }
  175.  
  176.  
  177. static int sound_fd_ready_to_read(int fd)
  178. {
  179.   struct timeval tv={0,0};
  180.   fd_set kbd_set,ex_set;
  181.   FD_ZERO(&kbd_set);
  182.   FD_SET(fd,&kbd_set);
  183.   memcpy((void *)&ex_set,(void *)&kbd_set,sizeof(ex_set));
  184.   select(FD_SETSIZE,&kbd_set,NULL,&ex_set,&tv);                // check for exception
  185.   if (FD_ISSET(fd,&ex_set))
  186.     die();
  187.   return (FD_ISSET(fd,&kbd_set));
  188. }
  189.  
  190.  
  191. void sound_watch()
  192. {
  193.   while (1)
  194.   {
  195.     while (sound_fd_ready_to_read(STDIN_FD))
  196.     {
  197.       uchar cmd;
  198.       if (read(STDIN_FD,&cmd,1)!=1)
  199.       { die(); }
  200.       switch (cmd)
  201.       {
  202.     case SFXCMD_REGISTER :
  203.     {
  204.       int shm_id;
  205.       long size;
  206.       uchar return_code;
  207.       if (read(STDIN_FD,&shm_id,sizeof(shm_id))!=sizeof(shm_id))
  208.       { fprintf(stderr,"sndrv er1\n"); die(); }
  209.       if (read(STDIN_FD,&size,sizeof(size))!=sizeof(size))
  210.       { fprintf(stderr,"sndrv er2\n"); die(); }
  211.  
  212.       sfx_handle *sfx=new sfx_handle;
  213.       sfx->shm_id=shm_id;
  214.       sfx->shm_data_pointer=shmat(shm_id,NULL,0);
  215.       if (!sfx->shm_data_pointer)
  216.       { fprintf(stderr,"Sound driver : unable to attach shared memory segment\n"); die(); }
  217.       sfx->size=size;
  218.       sfx->use_count=0;
  219.       sfx->next=sfx_list;
  220.       sfx_list=sfx;
  221.           
  222.       cmd=1;
  223.       if (write(STDOUT_FD,&cmd,sizeof(cmd))!=sizeof(cmd))
  224.       { fprintf(stderr,"sndrv er3\n"); die(); }
  225.  
  226.     } break;
  227.     case SFXCMD_UNREGISTER :
  228.     {
  229.       int shm_id,i;
  230.       sfx_handle *f,*find=NULL,*last_find=NULL;
  231.       if (read(STDIN_FD,&shm_id,sizeof(shm_id))!=sizeof(shm_id))
  232.       { die(); }
  233.       for (f=sfx_list;f && !find;f=f->next)   // see if we can find the shm id in list
  234.       {
  235.         if (f->shm_id==shm_id)
  236.           find=f;
  237.         last_find=find;         // svae last link so we can remove from the list
  238.       }
  239.       
  240.       if (find)
  241.       {
  242.         // see if there are any sound channels playing this sound, if so stop them because
  243.         // memory is fixing to be deleted
  244.         for (int i=0;i<NUM_CHANNELS;i++)
  245.         {
  246.           if (channels[i].snd==find)
  247.             channels[i].data=NULL;
  248.         }
  249.         // now free the memory
  250.         shmdt((char *)find->shm_data_pointer);          // detach and remove shm
  251.         if (last_find) 
  252.           last_find->next=find->next;           // unlink from sound list
  253.         else
  254.           sfx_list=sfx_list->next;
  255.       } else { fprintf(stderr,"Attempt to remove unknown sound effect\n"); die(); }
  256.     } break;
  257.  
  258.     case SFXCMD_PLAY :
  259.     {
  260.       int shm_id,i,volume;
  261.       sfx_handle *f;
  262.       if (read(STDIN_FD,&shm_id,sizeof(shm_id))!=sizeof(shm_id))
  263.         die();
  264.       if (read(STDIN_FD,&volume,sizeof(volume))!=sizeof(volume))
  265.         die();      
  266.  
  267.       for (f=sfx_list;f && f->shm_id!=shm_id;f=f->next);
  268.       if (f)
  269.         play(f,volume);
  270.       else fprintf(stderr,"sound driver : bad id to play\n");
  271.     } break;
  272.     default :     // die on unknown or DIE command
  273.     { die(); }
  274.       } 
  275.     }
  276.     output_sounds();
  277.   }
  278. }
  279.  
  280.  
  281. main()
  282. {
  283.   uchar success=sound_init();    // initailize sound and send status to who ever ran us.
  284.   if (!success)
  285.   {
  286.     printf("-1");
  287.     return 0;
  288.   }
  289.  
  290.   unlink(DIN_NAME);
  291.   unlink(DOUT_NAME);
  292.  
  293. //  int old_mask=umask(S_IRWXU | S_IRWXG | S_IRWXO);
  294.   if (mkfifo(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
  295.   { perror("Sound driver : unable to make fifo in /tmp");
  296.     return 0;
  297.   }
  298.   chmod(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
  299.  
  300.   if (mkfifo(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
  301.   { perror("Sound driver : unable to make fifo in /tmp");
  302.     return 0;
  303.   }
  304.  
  305.   chmod(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
  306.   //umask(old_mask);
  307.  
  308.   int chd=fork();
  309.   if (chd)
  310.   {
  311.     printf("%d\n",chd);         // tell parent the sound driver's process number
  312.     return 0;
  313.   }
  314.  
  315.   driver_out_fd=open(DOUT_NAME,O_RDWR);
  316.   if (driver_out_fd<0)
  317.   { perror(DOUT_NAME); 
  318.     exit(1);
  319.   }
  320.  
  321.   driver_in_fd=open(DIN_NAME,O_RDWR);
  322.   if (driver_in_fd<0)
  323.   { perror(DIN_NAME); 
  324.     exit(1);
  325.   }
  326.  
  327.   for (int i=0;i<TOTAL_SIGS;i++)
  328.     signal(sigs[i],clean_up);
  329.  
  330.   sound_watch();
  331.  
  332.   return 0;
  333. }
  334.  
  335.  
  336.  
  337.